package com.tzy.for10evalue.common;

import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;


@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResultEntity globalExceptionHandler(HttpServletRequest request, Exception ex) throws Exception {
        ResultEntity retDTO = new ResultEntity();
        retDTO.setSuccess(false);
        if (ex instanceof NoHandlerFoundException) {
            retDTO.setResultCode("404");
            retDTO.setResultMessage("路径不存在，请检查路径是否正确");
            return retDTO;
        } else if (ex instanceof RuntimeException) {  //这里一般换成公司封装的CommonException或者类似的AppException啥的
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(ex.getMessage());
            return retDTO;
        } else if (ex instanceof IllegalArgumentException) {
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(ex.getMessage());
            return retDTO;
        } else if (ex instanceof HttpRequestMethodNotSupportedException) {
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(ex.getMessage());
            return retDTO;
        } else if (ex instanceof MethodArgumentNotValidException) {
            String msg = ((MethodArgumentNotValidException) ex).getBindingResult().getAllErrors().stream()
                    .map(ObjectError::getDefaultMessage).collect(Collectors.joining(";"));
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(msg);
            return retDTO;
        } else if (ex instanceof MissingServletRequestParameterException) {
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(ex.getMessage());
            return retDTO;
        } else if (ex instanceof BindException) {
            // 入参校验，取有效的提示信息返回
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(null);
            List<FieldError> fieldErrors = ((BindException) ex).getBindingResult().getFieldErrors();
            if(!CollectionUtils.isEmpty(fieldErrors)){
                retDTO.setResultMessage(fieldErrors.get(0).getDefaultMessage());
            }
            return retDTO;
        } else if (ex instanceof ExcelAnalysisException) {
            // alibaba excel exception
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(ex.getCause().getMessage());
            return retDTO;
        } else if (ex instanceof HttpMessageNotReadableException) {
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(ex.getCause().getMessage());
            return retDTO;
        } else {
            if ("获取锁失败".equals(ex.getMessage())) {
                retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
                retDTO.setResultMessage("操作执行中,请勿重复提交!");
                return retDTO;
            }
            logger.error("异常URL:{}" + request.getRequestURL(), ex);
            String traceId = MDC.get("traceId");
            if (traceId != null) {
                traceId = "日志traceId=" + traceId + ",";
            } else {
                traceId = "";
            }
            retDTO.setResultCode(ResultEntity.SC_INTERNAL_SERVER_ERROR);
            retDTO.setResultMessage(ex.getMessage() + traceId);
        }
        return retDTO;
    }

}
